#include <stdlib.h>
#include <time.h>

//#include <log4c/log.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <cJSON/cJSON.h>
#include <server/export_symbol.h>
#include "session.h"

static se_head_st *s_session_head;
/**
 * 描述：初始化session头节点。
 *
 * 参数：无
 * 返回值：[错误]：NULL	[正确][se_head_st*]：session头节点地址
 *
 * 作者：王学飞
 * 日期：2016-3-4
 *
 *
 * **/
static se_head_st *init_session_head()
{
	se_head_st *head;
	head = (se_head_st *)malloc(sizeof(se_head_st));
	if(!head){
		//LOG_ERROR("malloc error!!!!");
		return head;
	}

	memset(head, 0, sizeof(se_head_st));

	head->session_head.next = head->session_head.prev = &head->session_head;
	head->cache_pos = &head->cache[0];
	pthread_rwlock_init(&head->rw_lock, NULL);
	return head;
}

/**
 * 描述：初始化session节点
 *
 * 参数：无
 * 返回值：[错误]：NULL [正确][se_session_st*]:session节点地址
 *
 * 作者：王学飞
 * 日期：2016-3-4
 *
 * **/
static se_session_st * init_session_node()
{
	se_session_st *node;

	node = (se_session_st *)malloc(sizeof(se_session_st));
	if(!node){
		//LOG_ERROR("malloc error!!!!");
		return node;
	}

	memset(node, 0, sizeof(se_session_st));
	node->next = node->prev = node;

	return node;
}

/**
 * 描述：更新session的快速缓存
 *
 * 参数：[se_head_st*]	[IN]	[se_head]:session头节点
 * 返回值：无
 *
 * 作者：王学飞
 * 日期：2016-3-4
 *
 * **/
static void update_session_cache(se_head_st *se_head, se_session_st *node)
{
	*(se_head->cache_pos) = node;
	if(se_head->cache_pos >= &se_head->cache[CACHE_NUM]){
		se_head->cache_pos = &se_head->cache[0];
	}else{
		se_head->cache_pos++;
	}
}
/**
 * 描述：将session节点插入链表。
 *
 * 参数：[se_head_st]	[IN]	[se_head]:session头节点
 * 		 [se_session_st][IN]	[node]:session节点
 * 返回值：[int]:无意义
 *
 * 作者：王学飞
 * 日期：2016-3-4
 *
 * **/
static int add_session_node(se_head_st *se_head, se_session_st *node)
{
	node->next = &se_head->session_head;
	node->prev = se_head->session_head.prev;
	se_head->session_head.prev->next = node;
	se_head->session_head.prev = node;
	*(se_head->cache_pos) = node;
	update_session_cache(se_head, node);
	return 0;
}

static cJSON *build_cj_session(se_session_st *node)
{
	cJSON *cj;
	cj = cJSON_CreateObject();
	if(!cj){
		return cj;
	}
	
	
}

/**
 * 描述：通过字符类型的session地址查找session节点
 *
 * 参数：[se_head_st]	[IN]	[se_head]:session头节点
 * 		 [char *]		[IN]	[sess_addr]:字符串的session地址
 * 返回值：[se_session_st*]	：session节点的地址
 *
 * 作者：王学飞
 * 日期：2016-3-4
 *
 * **/
static se_session_st *get_session_by_sess_key(se_head_st *se_head, char *sess_addr)
{
	se_session_st *se_addr;
	se_session_st *p;
	int i;

	if(!sess_addr){
		//LOG_ERROR("se_addr is NULL!!!!");
		return NULL;
	}

	sscanf(sess_addr, "%p", &se_addr);
	//LOG_DEBUG("seaddr = %p",se_addr);

	pthread_rwlock_wrlock(&se_head->rw_lock);

	for(i = 0; i < CACHE_NUM; i++){
		if(se_head->cache[i] == se_addr){
			pthread_rwlock_unlock(&se_head->rw_lock);
			return se_addr;
		}
	}
	p = se_head->session_head.next;

	while(p != &se_head->session_head){
		if(p == se_addr){
			update_session_cache(se_head,p);
			pthread_rwlock_unlock(&se_head->rw_lock);
			return se_addr;
		}
		p = p->next;	
	}
	pthread_rwlock_unlock(&se_head->rw_lock);
	return NULL;
}

/**
 * 描述：获取session节点
 *
 * 参数：[cJSON*]	[IN]	[arg]:RPC参数；
 * 返回值：[错误]：NULL [正确][cJSON*]：RPC返回值
 *
 * 作者：王学飞
 * 日期：2016-3-4
 *
 * **/
struct cJSON *se_get_session_node(cJSON *arg)
{
	struct cJSON *session;
	se_session_st *sess_ret;

	session = cJSON_GetObjectItem(arg, "session");
	if(!session){
		//LOG_ERROR("get session error!! [%s]",cJSON_GetErrorPtr());
		return NULL;
	}

	sess_ret = get_session_by_sess_key(s_session_head, session->valuestring);
	if(!sess_ret){
		//LOG_ERROR("session not found!!!");
		return NULL;
	}
	//TODO: session to cJSON;
}
/**
 * 描述：创建session节点
 *
 * 参数：[cJSON]	[IN]	[arg]:RPC参数
 * 返回值：[错误]：NULL [正确][cJSON*]RPC返回值；	
 *
 * 作者：王学飞
 * 日期：2016-3-4
 *
 * **/
struct cJSON *se_create_session(cJSON *arg)
{
	struct cJSON * cj;
	struct cJSON *account;
	struct cJSON *password;

	account = cJSON_GetObjectItem(arg, "account");
	if(!account){
		//LOG_ERROR("can't get account message %s!!!",cJSON_GetErrorPtr());
		return NULL;
	}

	password = cJSON_GetObjectItem(arg, "password");
	if(!password){
		//LOG_ERROR("can't get password error %s!!!!",cJSON_GetErrorPtr());
		return NULL;
	}
	//TODO:create session and return cJSON object;
}

/**
 * 描述：更新session时间戳
 *
 * 参数：[cJSON*]	[IN]	[arg]:RPC参数
 * 返回值：[错误]:NULL [正确][cJSON*]session节点地址
 *
 * 作者：王学飞
 * 日期：2016-3-4
 *
 * **/
struct cJSON *se_touch_session(cJSON *arg)
{
	struct cJSON *cj_account;
	struct cJSON *cj_session;
	struct cJSON *cj_sess_key;
	char *chp_sess_key;
	se_session_st *p;

	cj_account = cJSON_GetObjectItem(arg, "account");
	if(!cj_account){
		//LOG_ERROR("can't get password error %s!!!",cJSON_GetErrorPtr());
		return NULL;
	}

	cj_session = cJSON_GetObjectItem(arg, "session");
	if(!cj_session){
		//LOG_ERROR("can't get session error %s!!",cJSON_GetErrorPtr());
		return NULL;
	}

	cj_sess_key = cJSON_GetObjectItem(cj_session, "sess_key");
	if(!cj_sess_key){
		//LOG_ERROR("can't get sess_key %s !!",cJSON_GetErrorPtr());
		return NULL;
	}

	chp_sess_key = cj_sess_key->valuestring;

	p = get_session_by_sess_key(s_session_head, chp_sess_key);
	if(!p){
		//LOG_ERROR("can,t get sess_key %s !!",cJSON_GetErrorPtr());
		return NULL;
	}
}

/**
 * 描述：通过IP地址获取session节点
 *
 * 参数：[se_head_st]	[IN]	[head]:session头节点
 * 		 [char*]		[IN]	[addr]：字符串类型的IP地址"xxx.xxx.xxx.xxx"
 * 返回值：[错误]:NULL 	[正确][se_session_st]:session节点地址
 *
 * 作者：王学飞
 * 日期：2016-3-4
 *
 * **/
se_session_st *get_session_by_ip_addr(se_head_st *head, const char *addr)
{
	int i;
	se_session_st *p;

	pthread_rwlock_wrlock(&head->rw_lock);

	for(i = 0; i < CACHE_NUM; i++){
		if(!head->cache[i]){
			break;
		}
		if(!strcmp(head->cache[i]->addr, addr)){
			pthread_rwlock_unlock(&head->rw_lock);
			return head->cache[i];
		}
	}
	p = head->session_head.next;

	while(p != &head->session_head){
		if(!strcmp(p->addr, addr)){
			pthread_rwlock_unlock(&head->rw_lock);
			return p;
		}
		p = p->next;	
	}

	pthread_rwlock_unlock(&head->rw_lock);
}

/**
 * 描述：删除session节点，当客户端关闭时调用
 *
 * 参数：[cJSON*]	[IN]	[arg]:RPC参数
 * 返回值：[错误]：NULL  [正确][cJSON*]	:RPC返回值
 *
 * 作者：王学飞
 * 日期:2016-3-4
 *
 * **/
struct cJSON *se_destory_by_addr(cJSON *arg)
{
	cJSON *cj_addr;
	char *addr;
	se_session_st *s;

	//cj_addr = cJSON_GetObjectItem(arg, "Addr");
	//if(!cj_addr){
	//	LOG_ERROR("get addr error!!!");
//		return NULL;
//	}

	//addr = cj_addr->valuestring;
	//LOG_DEBUG("addr is %s",addr);
	//LOG_DEBUG("sock is %d",cJSON_GetObjectItem(arg,"SockFd")->valueint);
	//s = get_session_by_ip_addr(s_session_head, addr);
	return NULL;
}

int se_bc_test(cJSON *arg)
{
	//LOG_DEBUG("BROAD_TEST!!!");
}

/**
 * 描述：模块初始化函数。
 *
 * 参数：无
 * 返回值：无
 *
 * 作者：王学飞
 * 日期：2016-3-4
 *
 * **/
void sess_init(void)
{
	s_session_head = init_session_head();
	//LOG_DEBUG("sess_init");
}

/**
 * 描述：模块卸载函数
 *
 * 参数：无
 * 返回值：无
 *
 * 作者：王学飞
 * 日期：2016-3-4
 * 
 * **/
void sess_fini(void)
{
	//LOG_DEBUG("sess_fini");
}

static method_st sess_method[] = {
	{"se_create_session",1,se_create_session,NULL},
	{"se_get_session_node",2,se_get_session_node,NULL},
	{"se_destory_by_addr",3,se_destory_by_addr,NULL},
};

static bc_app_st sess_bc_method[] = {
	{LOGIN, se_bc_test, NULL},
	{LOGOUT, se_bc_test, NULL},
};

EXPORT_SYMBOL(sess_method);
EXPORT_BROADCAST(sess_bc_method);
